#ifndef TABLE_H
#define TABLE_H
#include <stdint.h>
#include <stdio.h>
#include <stdbool.h>
#include "pager.h"
// 表结构
#define COLUMN_USERNAME_SIZE 32
#define COLUMN_EMAIL_SIZE 255
typedef struct
{
    uint32_t id;
    char username[COLUMN_USERNAME_SIZE + 1];
    char email[COLUMN_EMAIL_SIZE + 1];
} Row;

#define size_of_attribute(Struct, Attribute) sizeof(((Struct *)0)->Attribute)

extern const uint32_t ID_SIZE;
extern const uint32_t USERNAME_SIZE;
extern const uint32_t EMAIL_SIZE;
extern const uint32_t ROW_SIZE;

extern const uint32_t ID_OFFSET;
extern const uint32_t USERNAME_OFFSET;
extern const uint32_t EMAIL_OFFSET;

extern const uint32_t PAGE_SIZE;

extern const uint32_t ROWS_PRE_PAGE;
extern const uint32_t TABLE_MAX_ROWS;

// 表结构
typedef struct
{
    uint32_t root_page_num; // 根节点的page_number
    Pager *pager;
} Table;

// 打印表
void print_row(Row *row);
// 通过filename读取表
Table *db_open(const char *filename);
void db_close(Table *table);

// source --> destination
void serialize_row(Row *source, void *destination);
// destination --> source
void deserialize_row(void *source, Row *destination);

// 表的迭代器
typedef struct
{
    Table *table;
    uint32_t page_num; // 叶节点的位置
    uint32_t cell_num; // 叶节点的第几个孩子
    bool end_of_table; // 是不是表的最后一列
} Cursor;

// 返回表的开头
Cursor *table_start(Table *table);

// 确定key在table对应的位置
Cursor *table_find(Table *table, uint32_t key);

// 迭代器前进一位
void cursor_advance(Cursor *cursor);

typedef struct _Leaf Leaf;

// 获取行数为迭代器对应行的首地址
Leaf *cursor_value(Cursor *cursor);

#pragma pack(push, 1) // 指定接下来的结构体按1字节对齐

// 叶节点的数据
struct _Leaf
{
    uint32_t key;
    Row value;
};

// 叶节点
typedef struct _Node
{
    uint8_t node_type;
    uint8_t is_root;
    uint32_t parent_pointer;
    uint32_t num_cells;
    uint32_t next_leaf_page;
    Leaf rows[13]; // 根据给定的数据，计算出是这个值，PAGE_SIZE / ROW_PREPAGE
} Node;
// 内部节点数据
typedef struct _Internal_Leaf
{
    //顺序千万不能错，child_pointer key child_pointer 这样的形式
    uint32_t child_page;
    uint32_t key;
} Internal_Leaf;

#define INTERNAL_NODE_MAX_KEY 5
#define INTERNAL_NODE_LEFT_KEY 3 //裂开后，左孩子的key的数量
#define INTERNAL_NODE_RIGHT_KEY 3 //裂开后，左孩子的key的数量

// 内部节点
typedef struct _Internal_Node
{
    uint8_t node_type;
    uint8_t is_root;
    uint32_t parent_pointer;
    uint32_t num_keys;
    //正常情况，这里我们写5，方便测试后面的
    //Internal_Leaf internal_leaf[510];
    Internal_Leaf internal_leaf[INTERNAL_NODE_MAX_KEY+1];
} Internal_Node;

#pragma pack(pop) // 恢复到之前的对齐模式

#endif // TABLE_H